<template>
	<div class="editor-container">
		<Toolbar :editor="editorRef" :mode="mode" :defaultConfig="state.toolbarConfig"/>
		<Editor
			:mode="mode"
			:defaultConfig="state.editorConfig"
			:style="{ height }"
			v-model="state.editorVal"
			@onCreated="handleCreated"
			@onChange="handleChange"
		/>
	</div>
</template>

<script setup lang="ts" name="wngEditor">
// https://www.wangeditor.com/v5/for-frame.html#vue3
import '@wangeditor/editor/dist/css/style.css';
import { reactive, shallowRef, watch, onBeforeUnmount } from 'vue';
import { IDomEditor, Boot } from '@wangeditor/editor';
import { Toolbar, Editor } from '@wangeditor/editor-for-vue';
// import { MyButtonMenu } from '/@/components/editor/source';
import { parseCodeEditor, parseEditorCode, sourceConf } from "./tool";

// 定义父组件传过来的值
const props = defineProps({
	// 是否禁用
	disable: {
		type: Boolean,
		default: () => false,
	},
	// 内容框默认 placeholder
	placeholder: {
		type: String,
		default: () => '请输入内容...',
	},
	// https://www.wangeditor.com/v5/getting-started.html#mode-%E6%A8%A1%E5%BC%8F
	// 模式，可选 <default|simple>，默认 default
	mode: {
		type: String,
		default: () => 'default',
	},
	// 高度
	height: {
		type: String,
		default: () => '310px',
	},
	// 双向绑定，用于获取 editor.getHtml()
	getHtml: String,
	// 双向绑定，用于获取 editor.getText()
	getText: String,
	readOnly: {
		type: Boolean,
		default: () => false,
	}
});

// 定义子组件向父组件传值/事件
const emit = defineEmits(['update:getHtml', 'update:getText']);

// 定义变量内容
const editorRef = shallowRef();
const state = reactive({
	toolbarConfig: {
		insertKeys: {
			index: 0, // 插入的位置，基于当前的 toolbarKeys
    	keys: ['source']
		}
	},
	editorConfig: {
		readOnly: props.readOnly,
		placeholder: props.placeholder,
		MENU_CONF: {
		// 上传图片配置
			uploadImage: {
				server: import.meta.env.VITE_API_URL + 'v1/uploadFileV1', //'http://localhost:8888/api/v1/uploadFileV1',// import.meta.env.VITE_API_URL + 'v1/uploadFileV1',
				timeout: 30 * 1000,
				fieldName: 'file',
				meta: {},
				metaWithUrl: false,
				headers: { Authorization: '' },
				maxFileSize: 10 * 1024 * 1024, // 10M
				base64LimitSize: 5 * 1024, // insert base64 format, if file's size less than 5kb
				onBeforeUpload(file:any) {
					return file;
				},
				onProgress(progress:any) {},
				onSuccess(file:any, res:any) {
					// console.log('onSuccess', file, res);
				},
				onFailed(file:any, res:any) {
					// console.log('onFailed', file, res);
				},
				onError(file:any, err:any, res:any) {},
				customInsert(res:any, insertFn:any) {
					if(res.status === 'success') {
						insertFn(res.data.url, '', '');
					}	
				},
			},
			uploadVideo: {
				server: import.meta.env.VITE_API_URL + 'v1/uploadFileV1',//'http://localhost:8888/api/v1/uploadFileV1',// 
				timeout: 5 * 1000,
				fieldName: 'file',
				meta: {},
				metaWithUrl: false, // join params to url
				headers: { Authorization: '' },
				maxFileSize: 10 * 1024 * 1024, // 10M
				onBeforeUpload(file:any) {
					return file;
				},
				onProgress(progress:any) {},
				onSuccess(file:any, res:any) {
					// console.log('onSuccess', file, res);
				},
				onFailed(file:any, res:any) {
					// console.log('onFailed', file, res);
				},
				onError(file:any, err:any, res:any) {},
				customInsert(res:any, insertFn:any) {
					if(res.success === 'success') {
						insertFn(res.data.url, '', '');
					}	
				},
			},
		},
		withCredentials:true,
	},
	editorVal: props.getHtml,
});

/**
 * 源码点击
 * @param active 菜单是否点击
 * @param editor 编辑器内容
 */
const clickSource = (active: boolean, editor: IDomEditor) => {
	let value = editor.getHtml();
	// 先将编辑器内容清空
	editor.clear();
	if (active) {
			// 将html代码转换为html代码块 dangerouslyInsertHtml是插入html不是重置html，如果使用setHtml也会报节点异常
			editor.dangerouslyInsertHtml(parseEditorCode(value));
	} else {
			// 将html代码块转换为editor的html
			editor.dangerouslyInsertHtml(parseCodeEditor(value));
			value = parseCodeEditor(value);
	}
}

// 编辑器回调函数
const handleCreated = (editor: IDomEditor) => {
	if (!editor.getAllMenuKeys().includes('source')) {
			Boot.registerMenu(sourceConf);
	}
	// 源码菜单点击监听事件
	editor?.on('clickSource', (active) => clickSource(active, editor));
	editorRef.value = editor;
};
// 编辑器内容改变时
const handleChange = (editor: IDomEditor) => {
	emit('update:getHtml', editor.getHtml());
	emit('update:getText', editor.getText());
};



// 页面销毁时
onBeforeUnmount(() => {
	const editor = editorRef.value;
	if (editor == null) return;
	editor.destroy();
});
// 监听是否禁用改变
// https://gitee.com/lyt-top/vue-next-admin/issues/I4LM7I
watch(
	() => props.disable,
	(bool) => {
		const editor = editorRef.value;
		if (editor == null) return;
		bool ? editor.disable() : editor.enable();
	},
	{
		deep: true,
	}
);
// 监听双向绑定值改变，用于回显
watch(
	() => props.getHtml,
	(val) => {
		state.editorVal = val;
	},
	{
		deep: true,
	}
);
</script>

<style lang="scss" scoped>
.editor-container {
	width: 100%;
	overflow: auto;
}
</style>

